home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C++
/
Snippets
/
SuperSplash 1.0d1
/
sources
/
•AZN_SUPER_SPLASH
/
AZN_TSuperSplash.cp
next >
Wrap
Text File
|
1995-10-20
|
14KB
|
595 lines
/*
* AZN_TSuperSplash.cp
*
* Class implementation for 'TSuperSplash' class, a class
* to put up and manage a splash screen
* Inheritance: BASE CLASS
*
* © Andrew Nemeth Warrimoo Australia 1995
* aznemeng@zeta.org.au
*
* File opened: 20 Jul 95
* File ammended: 20–23 Jul;
* 16, 22, 23, 25 Sep;
* 20 Oct 95
*/
#include "AZN_TSuperSplash.h" // put up & manage Splash screen
#include "JPEGUtilities.h" // Aaron Giles JPEG utility package
#include "AZN_DBUG.H" // debugging utilites
#include <Quickdraw.h>
#include <Memory.h> // Mac 'TempXXXHandle()' traps
#include <Files.h>
#include <Aliases.h>
#include <Processes.h>
#include <Gestalt.h>
#include <LowMem.h> // Allows access to low mem globals
// FILE DEFINES
//
#define kMoveToFront (WindowPtr)-1L
const OSType kostypePICTtype = 'PICT',
kostypeJPEGtype = 'JPEG';
TSuperSplash::TSuperSplash ()
: f_OldGrafPort( NULL ),
f_ptrWind( NULL ),
f_hPict( NULL ),
f_shPictRes_ID( -1 ),
f_boolBigImg( FALSE )
{
f_str63FileName[0] = 0;
}
TSuperSplash::TSuperSplash ( const short shPictRes_ID )
: f_OldGrafPort( NULL ),
f_ptrWind( NULL ),
f_hPict( NULL ),
f_shPictRes_ID( shPictRes_ID ),
f_boolBigImg( FALSE )
//
// Construct with PICT resource ID
//
{
f_str63FileName[0] = 0;
}
TSuperSplash::TSuperSplash ( ConstStr63Param str63Name )
: f_OldGrafPort( NULL ),
f_ptrWind( NULL ),
f_hPict( NULL ),
f_shPictRes_ID( -1 ),
f_boolBigImg( FALSE )
//
// Construct with filename
//
{
ASSERT( NULL != str63Name );
::BlockMoveData( (StringPtr)str63Name, f_str63FileName, str63Name[0] + 1 );
}
TSuperSplash::~TSuperSplash ()
//
// Destruct by getting rid of window
//
{
killSplash();
}
Boolean TSuperSplash::showSplash ( void )
//
// Put up splash according to if
// 1. PICT res ID given or...
// 2. Graphics filename in home directory given
//
{
FSSpec fsspecFile = { 0, 0L, "\p" };
OSErr myErr = noErr;
// idiot filters
ASSERT( f_shPictRes_ID > 0 || f_str63FileName[0] > 0 );
// using PICT res ID
if ( f_shPictRes_ID > 0 )
{
f_hPict = ::GetPicture( f_shPictRes_ID );
if ( f_hPict )
{
// pry PICT free of resource map!
::DetachResource( (Handle)f_hPict );
drawSplash( f_hPict );
return( TRUE );
// N.B. No need to dispose of PicHandle here as
// it is disposed when 'killWindow()' is called
}
}
// using filename
else if ( f_str63FileName[0] > 0 )
{
if ( noErr == grabNamedFile( f_str63FileName, &fsspecFile ) )
return( showSplash( fsspecFile ) );
}
return( FALSE );
}
Boolean TSuperSplash::showSplash ( const FSSpec & fsspecFile )
//
// Given the FSSpec of a PICT or JPEG file
// extract image from data fork,
// load it into a PicHandle,
// assign to class var 'f_hPict'
// and then put up splash
//
{
OSErr myErr = noErr;
// get rid of any existing
killSplash();
if ( noErr == grabPictHandleFromFile( fsspecFile, &f_hPict ) )
{
drawSplash( f_hPict );
return( TRUE );
}
return( FALSE );
}
void TSuperSplash::killSplash ( void )
//
// Zap PicHandle, window & restore GrafPort
//
{
if ( f_hPict )
::DisposeHandle( (Handle)f_hPict );
if ( f_ptrWind )
::DisposeWindow( f_ptrWind );
if ( f_OldGrafPort )
::SetPort( f_OldGrafPort );
f_hPict = NULL;
f_ptrWind = f_OldGrafPort = NULL;
}
void TSuperSplash::drawSplash ( PicHandle hSplashPICT )
//
// Given a PicHandle, create window & get splash on screen
// N.B. ASSUMES 'PicHandle' is a free-standing handle
// and not part of a resource map! This is because
// 'DisposeHandle()' is called if something goes wrong!!!
//
{
const Str31 kstr31_Prompt = { "\pLoading image…" };
const short kshWindowKind = altDBoxProc,
kshBlackPattern = 1;
Pattern recPattern;
Rect rectPICT = { 0, 0, 10, 10 };
// idiot filters
ASSERT( NULL != hSplashPICT );
ASSERT( NULL == f_ptrWind );
ASSERT( NULL == f_OldGrafPort );
// save current GrafPort
::GetPort( &f_OldGrafPort );
::SetCursor( *GetCursor(watchCursor) );
// create window
if ( hasColourQD() )
f_ptrWind = ::NewCWindow( NULL, &rectPICT, NULL, FALSE, kshWindowKind,
kMoveToFront, FALSE, 0L );
else
f_ptrWind = ::NewWindow( NULL, &rectPICT, NULL, FALSE, kshWindowKind,
kMoveToFront, FALSE, 0L );
// return if new window failed
if ( NULL == f_ptrWind )
return;
// size the window so PICT will fit!
f_ptrWind->portRect = (**(hSplashPICT)).picFrame;
// place window in ALRT position
centreWindow( f_ptrWind, TRUE );
// assign where to draw the pict!
rectPICT = f_ptrWind->portRect;
// grab a pattern from system
::GetIndPattern( &recPattern, sysPatListID, kshBlackPattern );
// Why do it this way? Because we can then access
// *all* the system patterns, not just those held
// in the Quickdraw global 'qd'.
// get window on screen
::SetPort( f_ptrWind );
::ShowWindow( f_ptrWind );
::BeginUpdate( f_ptrWind );
if ( f_boolBigImg )
{
// fill window with system pattern
::FillRect( &(f_ptrWind->portRect), &recPattern );
// put prompt in top LHS
::MoveTo( rectPICT.left+10, rectPICT.top+15 );
::TextSize( 9 );
::TextMode( notSrcCopy );
::DrawString( kstr31_Prompt );
::PenNormal();
}
// draw PICT
::DrawPicture( hSplashPICT, &rectPICT );
::EndUpdate( f_ptrWind );
::SetCursor( &qd.arrow );
}
OSErr TSuperSplash::grabNamedFile ( ConstStr63Param str63Name,
FSSpecPtr ptrfsspecFile )
//
// 1. Grabs file with name matching that in 'str63Name'
// 2. Looks in current app's 'home' directory only!
// 3. Resolves an alias (if necessary)
// 4. Loads FSSpec into ptr provided & returns OSErr
//
{
const Boolean kboolResolveAliasChains = TRUE;
FSSpec fsspecDummy = { 0, 0L, "\p" };
Boolean boolIsFolder = FALSE,
boolWasAlias = FALSE;
short shVRefNum = 0;
long lgParID = 0;
OSErr myErr = noErr;
// idiot filters
ASSERT( NULL != ptrfsspecFile );
ASSERT( str63Name[0] > 0 );
// grab 'home directory' co-ords
myErr = grabVol_ParId( &shVRefNum, &lgParID );
// create FSSpec for target file
if ( noErr == myErr )
myErr = ::FSMakeFSSpec( shVRefNum, lgParID, str63Name,
&fsspecDummy );
// resolve alias (if necessary)
if ( noErr == myErr )
{
myErr = ::ResolveAliasFile( &fsspecDummy, kboolResolveAliasChains,
&boolIsFolder, &boolWasAlias );;
if ( noErr == myErr && boolIsFolder )
myErr = fnfErr;
}
// assign result only if file exists! (noErr)
if ( noErr == myErr )
::BlockMoveData( &fsspecDummy, ptrfsspecFile, sizeof( FSSpec ) );
return( myErr );
}
OSErr TSuperSplash::grabVol_ParId ( short * ptrshVol, long * ptrlgParID )
//
// Grab the 'vRefNum' & 'parID' of the
// currently running application (ie. the 'HOME' dir)
//
{
ProcessSerialNumber psnCurrent;
ProcessInfoRec procirRec;
FSSpec fsspecDummy;
OSErr myErr = noErr;
// idiot filters
ASSERT( NULL != ptrshVol );
ASSERT( NULL != ptrlgParID );
// grab PSN of current process
myErr = ::GetCurrentProcess( &psnCurrent );
// now grab its details
if ( noErr == myErr )
{
procirRec.processInfoLength = sizeof( ProcessInfoRec );
procirRec.processName = NULL;
procirRec.processAppSpec = &fsspecDummy;
myErr = ::GetProcessInformation( &psnCurrent, &procirRec );
}
// assign values
if ( noErr == myErr )
{
*ptrshVol = fsspecDummy.vRefNum;
*ptrlgParID = fsspecDummy.parID;
}
return( myErr );
}
OSErr TSuperSplash::grabPictHandleFromFile ( const FSSpec & fsspecFile,
PicHandle * ptrPictHandle )
//
// Given a PICT or JPEG type file, extract the data
// from the data fork, create a handle and dump data
// in as PICT handle.
//
// Because image could be any size, we use
// System Heap Temporary Memory.
//
{
enum EFileType{ kshIsPICT, kshIsJPEG, kshInvalid };
const long klgPICT_Header = 512L;
EFileType enumFType;
long lgHandleSize = 0L;
short shRefNum = -1;
Handle hData = NULL;
OSErr myErr = noErr;
// idiot filter
ASSERT( NULL != ptrPictHandle );
*ptrPictHandle = NULL;
// reset 'large img' flag
f_boolBigImg = FALSE;
// Examine file type
//
if ( isFileOfType( fsspecFile, kostypePICTtype ) )
enumFType = kshIsPICT;
else if ( isFileOfType( fsspecFile, kostypeJPEGtype ) )
enumFType = kshIsJPEG;
else
enumFType = kshInvalid;
// Process file according to type
//
switch ( enumFType )
{
case kshIsPICT:
// open data fork of file
myErr = ::FSpOpenDF( (FSSpecPtr)&fsspecFile,
fsRdPerm,
&shRefNum );
// figure size of PICT
if ( noErr == myErr )
myErr = ::GetEOF( shRefNum, &lgHandleSize );
if ( noErr == myErr )
myErr = ( lgHandleSize > klgPICT_Header ) ? noErr : eofErr;
// create handle to hold pict
if ( noErr == myErr )
{
// PicHandle size is size of data fork, less
// the PICT header ('klgPICT_Header').
//
lgHandleSize -= klgPICT_Header;
// allocate handle on SYSTEM heap!
if ( ::TempFreeMem() > lgHandleSize )
{
*ptrPictHandle = (PicHandle)::TempNewHandle( lgHandleSize, &myErr );
//
// Some notes about this. With System 6, to dispose you would
// need to call '::TempDisposeHandle()', but with system 7
// '::DisposeHandle()' works just as well
//
// See Think Reference entry on 'About Temporary Memory'
//
if ( NULL == *ptrPictHandle )
myErr = memFullErr;
}
else
myErr = memFullErr;
}
// now read data into PicHandle
if ( noErr == myErr )
{
::SetFPos( shRefNum, fsFromStart, klgPICT_Header );
// lock as 'FSRead' can move memory
::HLock( (Handle)*ptrPictHandle );
myErr = ::FSRead( shRefNum, &lgHandleSize, (Ptr)**ptrPictHandle );
::HUnlock( (Handle)*ptrPictHandle );
}
break;
case kshIsJPEG:
// need Quicktime for JPEG
if ( quicktimeAvailable() )
{
myErr = ::FSpOpenDF( (FSSpecPtr)&fsspecFile,
fsRdPerm,
&shRefNum );
// figure size of image
if ( noErr == myErr )
myErr = ::GetEOF( shRefNum, &lgHandleSize );
if ( noErr == myErr )
myErr = ( lgHandleSize > 0L ) ? noErr : eofErr;
// create handle to hold image
if ( noErr == myErr )
{
if ( ::TempFreeMem() > lgHandleSize )
{
hData = ::TempNewHandle( lgHandleSize, &myErr );
if ( NULL == hData )
myErr = memFullErr;
}
else
myErr = memFullErr;
}
// now read data into handle
if ( noErr == myErr )
{
::HLock( hData );
myErr = ::FSRead( shRefNum, &lgHandleSize, (Ptr)*hData );
::HUnlock( hData );
}
// convert JPEG data to PICT
if ( noErr == myErr && lgHandleSize > 0L )
{
*ptrPictHandle = (PicHandle)::WrapJPEG( hData );
f_boolBigImg = TRUE;
}
}
else
myErr = fnfErr;
break;
case kshInvalid:
myErr = fnfErr;
break;
}
return( myErr );
}
Boolean TSuperSplash::isFileOfType ( const FSSpec & fsspecFile,
const OSType ostypeFile )
//
// Is file of type 'ostypeFile'?
//
{
HFileInfo finfoRec;
Boolean boolResult = FALSE;
OSErr myErr = noErr;
// idiot filter
ASSERT( ostypeFile > 0L );
// set up block for cat. lookup
finfoRec.ioNamePtr = (StringPtr)fsspecFile.name;
finfoRec.ioVRefNum = fsspecFile.vRefNum;
finfoRec.ioDirID = fsspecFile.parID;
finfoRec.ioFDirIndex = 0;
// look up catalogue
myErr = ::PBGetCatInfoSync( (CInfoPBPtr)&finfoRec );
if ( noErr == myErr )
{
// examing file (and not directories!)
if ( ( finfoRec.ioFlAttrib & ioDirMask ) == 0 )
{
if ( ostypeFile == finfoRec.ioFlFndrInfo.fdType )
boolResult = TRUE;
}
}
return( boolResult );
}
Boolean TSuperSplash::hasColourQD ( void )
//
// STATIC FUNCTION!
// Use gestalt to see if Colour QD is present
//
{
const long klgGestaltMask = 1L;
long lgFeature = 0L;
OSErr myErr = noErr;
myErr = ::Gestalt( gestaltQuickdrawFeatures, &lgFeature );
if ( ( myErr == noErr ) && ( lgFeature & ( klgGestaltMask << gestaltHasColor ) ) )
return( TRUE );
else
return( FALSE );
}
Boolean TSuperSplash::quicktimeAvailable ( void )
//
// Use Gestalt to see if Quicktime is available
// (Needed by JPEG code!)
//
// Assume 'available' if Quicktime version > 2.0
//
{
const long klgGestaltMask = 1L;
long lgFeature = 0L;
OSErr myErr = noErr;
myErr = ::Gestalt( gestaltQuickTimeVersion, &lgFeature );
if ( ( myErr == noErr ) && ( lgFeature >= 0x0200 ) )
return( TRUE );
else
return( FALSE );
}
void TSuperSplash::centreWindow ( WindowPtr ptrWind, Boolean boolALRTpos )
//
// Given a WindowPtr, centre it on screen (or
// place it in ALRT position). Code always makes
// sure that new position never puts window
// below the menuBar.
//
{
const short kshMBarHeight = LMGetMBarHeight(),
kshScreen_Width = qd.screenBits.bounds.right,
kshScreen_Height = qd.screenBits.bounds.bottom,
kshPos = boolALRTpos ? 3 : 2,
kshVertMin = kshMBarHeight + 2;
Rect rectWind;
short x, y = 0;
// sanity check
if ( ptrWind == NULL )
return;
else
rectWind = ptrWind->portRect;
// calc new offsets
::OffsetRect( &rectWind, -rectWind.left, -rectWind.top );
x = ( kshScreen_Width - rectWind.right ) / 2;
y = kshMBarHeight + ( ( kshScreen_Height - rectWind.bottom - kshMBarHeight ) / kshPos );
// make sure window is always below mbar!
y = ( y < kshVertMin) ? kshVertMin : y;
::MoveWindow( ptrWind, x, y, FALSE );
}